package com.clear.honghefinance.biz.modules.voucher.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.clear.honghefinance.biz.modules.system.member.domain.vo.AdminDTO;
import com.clear.honghefinance.biz.modules.voucher.converter.VoucherWordConfigConverter;
import com.clear.honghefinance.biz.modules.voucher.domain.dto.CreateVoucherWordConfigDTO;
import com.clear.honghefinance.biz.modules.voucher.domain.dto.DeleteVoucherWordConfigDTO;
import com.clear.honghefinance.biz.modules.voucher.domain.dto.UpdateVoucherWordConfigDTO;
import com.clear.honghefinance.biz.modules.voucher.domain.dto.UpdateVoucherWordConfigDefaultFlagDTO;
import com.clear.honghefinance.biz.modules.voucher.domain.entity.VoucherWordConfig;
import com.clear.honghefinance.biz.modules.voucher.domain.vo.GetVoucherWordConfigDetailVO;
import com.clear.honghefinance.biz.modules.voucher.domain.vo.ListVoucherWordConfigVO;
import com.clear.honghefinance.biz.modules.voucher.mapper.VoucherWordConfigMapper;
import com.clear.honghefinance.biz.modules.voucher.service.IVoucherWordConfigService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.clear.honghefinance.common.exception.BizException;
import com.clear.honghefinance.common.service.TokenService;
import com.clear.honghefinance.common.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 凭证字配置 服务实现类
 * </p>
 *
 * @author 程序员clear
 * @since 2024-08-22
 */
@Service
@Slf4j
public class VoucherWordConfigServiceImpl extends ServiceImpl<VoucherWordConfigMapper, VoucherWordConfig> implements IVoucherWordConfigService {

    @Resource
    private TokenService<AdminDTO> tokenService;
    @Resource
    private TransactionTemplate transactionTemplate;

    /**
     * 创建凭证字
     *
     * @param dto
     * @return
     */
    @Override
    public boolean create(CreateVoucherWordConfigDTO dto) {
        if (log.isInfoEnabled()) {
            log.info("创建凭证字中，入参：{}", JSON.toJSONString(dto));
        }
        VoucherWordConfig voucherWordConfig = getByVoucherWord(dto.getVoucherWord());
        if (voucherWordConfig != null) {
            throw new BizException("凭证字已存在");
        }
        try {
            VoucherWordConfig voucherWord = VoucherWordConfigConverter.INSTANCE.convertDTOToVoucherWordConfigEntity(dto);
            voucherWord.setMemberId(tokenService.getThreadLocalUserId());
            voucherWord.setTenantId(tokenService.getThreadLocalTenantId());
            voucherWord.initDefault();

            return this.save(voucherWord);
        } catch (Exception e) {
            log.error("创建凭证字异常 {}", e.getMessage(), e);
            throw new BizException("创建凭证字异常");
        }
    }

    /**
     * 修改凭证字
     *
     * @param dto
     * @return
     */
    @Override
    public boolean update(UpdateVoucherWordConfigDTO dto) {
        if (log.isInfoEnabled()) {
            log.info("编辑凭证字中，入参：{}", JSON.toJSONString(dto));
        }
        VoucherWordConfig voucherWordConfig = this.getByVoucherWord(dto.getVoucherWord());
        // 凭证字已存在，不能重复
        if (Objects.nonNull(voucherWordConfig) && !Objects.equals(dto.getId(), voucherWordConfig.getId())) {
            throw new BizException("凭证字已存在");
        }
        try {
            VoucherWordConfig voucherWord = VoucherWordConfigConverter.INSTANCE.convertDTOToVoucherWordConfigEntity(dto);
            voucherWord.setUpdateMemberId(tokenService.getThreadLocalUserId());
            voucherWord.setUpdateTime(DateUtil.getSystemTime());

            LambdaUpdateWrapper<VoucherWordConfig> lambdaUpdateWrapper = Wrappers.<VoucherWordConfig>lambdaUpdate()
                    .eq(VoucherWordConfig::getId, dto.getId())
                    // 只能修改当前租户下的凭证字
                    .eq(VoucherWordConfig::getTenantId, tokenService.getThreadLocalTenantId());

            if (!this.update(voucherWord, lambdaUpdateWrapper)) {
                throw new BizException("修改凭证字失败");
            }
            return true;
        } catch (Exception e) {
            log.error("编辑凭证字异常 {}", e.getMessage(), e);
            throw new BizException("修改凭证字失败");
        }
    }

    /**
     * 修改默认凭证字
     *
     * @param dto
     * @return
     */
    @Override
    public boolean updateDefaultFlag(UpdateVoucherWordConfigDefaultFlagDTO dto) {
        if (log.isInfoEnabled()) {
            log.info("修改默认凭证字中，入参：{}", JSON.toJSONString(dto));
        }
        try {
            transactionTemplate.execute(transactionStatus -> {
                // 清除默认的凭证字
                boolean clearFlag = this.update(Wrappers.<VoucherWordConfig>lambdaUpdate()
                        .eq(VoucherWordConfig::getDefaultFlag, true)
                        .eq(VoucherWordConfig::getTenantId, tokenService.getThreadLocalTenantId())
                        .set(VoucherWordConfig::getDefaultFlag, false)
                        .set(VoucherWordConfig::getUpdateMemberId, tokenService.getThreadLocalUserId())
                        .set(VoucherWordConfig::getUpdateTime, DateUtil.getSystemTime()));

                boolean updateFlag = this.update(Wrappers.<VoucherWordConfig>lambdaUpdate()
                        .eq(VoucherWordConfig::getId, dto.getId())
                        .eq(VoucherWordConfig::getTenantId, tokenService.getThreadLocalTenantId())
                        .eq(VoucherWordConfig::getDelFlag, false)
                        .eq(VoucherWordConfig::getDefaultFlag, true)
                        // 只能修改当前租户下
                        .set(VoucherWordConfig::getDefaultFlag, true)
                        .set(VoucherWordConfig::getUpdateMemberId, tokenService.getThreadLocalUserId())
                        .set(VoucherWordConfig::getUpdateTime, DateUtil.getSystemTime()));
                if (clearFlag && updateFlag) {
                    return true;
                }
                throw new BizException("修改默认凭证字失败");
            });
            return true;
        } catch (Exception e) {
            log.error("修改默认凭证字失败 {}", e.getMessage(), e);
            throw new BizException("修改默认凭证字失败");
        }
    }

    /**
     * 删除凭证字
     *
     * @param dto
     * @return
     */
    @Override
    public boolean delete(DeleteVoucherWordConfigDTO dto) {
        if (log.isInfoEnabled()) {
            log.info("删除凭证字中，入参：{}", JSON.toJSONString(dto));
        }
        try {
            LambdaUpdateWrapper<VoucherWordConfig> lambdaUpdateWrapper = Wrappers.<VoucherWordConfig>lambdaUpdate()
                    .eq(VoucherWordConfig::getId, dto.getId())
                    .eq(VoucherWordConfig::getDelFlag, false)
                    // 目前只能删除自己的凭证字
                    .eq(VoucherWordConfig::getTenantId, tokenService.getThreadLocalTenantId())
                    // 只能删除未使用的凭证字
                    .eq(VoucherWordConfig::getUseCount, 0)
                    // 只能删除未禁用的凭证字
                    .eq(VoucherWordConfig::getDelFlag, false)
                    .set(VoucherWordConfig::getDelFlag, true)
                    .set(VoucherWordConfig::getUpdateMemberId, tokenService.getThreadLocalUserId())
                    .set(VoucherWordConfig::getUpdateTime, DateUtil.getSystemTime());

            if (this.update(lambdaUpdateWrapper)) {
                return true;
            } else {
                if (log.isInfoEnabled()) {
                    log.info("删除凭证字异常，入参：{}", JSON.toJSONString(dto));
                }
                throw new BizException("删除凭证字失败");
            }
        } catch (Exception e) {
            log.error("删除凭证字异常 {}", e.getMessage(), e);
            throw new BizException("删除凭证字失败");
        }
    }

    /**
     * 查询凭证字列表（暂不需要分页）
     *
     * @return
     */
    @Override
    public List<ListVoucherWordConfigVO> listAll() {
        log.info("查看凭证字列表中");
        try {
            LambdaQueryWrapper<VoucherWordConfig> lambdaQueryWrapper = Wrappers.<VoucherWordConfig>lambdaQuery()
                    .eq(VoucherWordConfig::getDelFlag, false)
                    // 只能查到当前租户的凭证字
                    .eq(VoucherWordConfig::getTenantId, tokenService.getThreadLocalTenantId())
                    // 根据是否是本位币降序
                    .orderByDesc(VoucherWordConfig::getDefaultFlag)
                    // 根据编码升序
                    .orderByAsc(VoucherWordConfig::getVoucherWord);

            List<VoucherWordConfig> list = this.list(lambdaQueryWrapper);
            return VoucherWordConfigConverter.INSTANCE.convertEntityToVO(list);

        } catch (Exception e) {
            log.error("查询凭证字异常 {}", e.getMessage(), e);
            throw new BizException("查询凭证字异常");
        }
    }

    /**
     * 获取凭证字详情
     *
     * @param id
     * @return
     */
    @Override
    public GetVoucherWordConfigDetailVO getDetailById(long id) {
        log.info("查看凭证字明细中，入参：{}", id);
        try {
            LambdaQueryWrapper<VoucherWordConfig> lambdaQueryWrapper = Wrappers.<VoucherWordConfig>lambdaQuery()
                    .eq(VoucherWordConfig::getId, id)
                    .eq(VoucherWordConfig::getDelFlag, false)
                    // 只能查到当前租户的凭证字
                    .eq(VoucherWordConfig::getTenantId, tokenService.getThreadLocalTenantId());
            VoucherWordConfig voucherWordConfig = this.getOne(lambdaQueryWrapper);
            if (Objects.isNull(voucherWordConfig)) {
                throw new BizException("凭证字不存在");
            }
            return VoucherWordConfigConverter.INSTANCE.convertVoucherWordConfigEntityToGetVoucherWordConfigDetailVO(voucherWordConfig);
        } catch (Exception e) {
            log.error("查看凭证字明细异常 {}", e.getMessage(), e);
            throw new BizException("查看凭证字明细异常");
        }
    }


    /**
     * 查询凭证字信息
     *
     * @param voucherWord
     * @return
     */
    private VoucherWordConfig getByVoucherWord(String voucherWord) {
        return this.getOne(Wrappers.<VoucherWordConfig>lambdaQuery()
                .eq(VoucherWordConfig::getVoucherWord, voucherWord)
                // 只能查到当前租户的凭证字
                .eq(VoucherWordConfig::getTenantId, tokenService.getThreadLocalTenantId())
                .eq(VoucherWordConfig::getDelFlag, false)
        );
    }
}
